package com.bsg.upm.service;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bsg.upm.constant.DictConstants;
import com.bsg.upm.constant.DictTypeConstants;
import com.bsg.upm.constant.MonitorCommonMap;
import com.bsg.upm.dao.DictDao;
import com.bsg.upm.dao.MonitorEventDao;
import com.bsg.upm.dao.SystemConfigDao;
import com.bsg.upm.entity.AreaEntity;
import com.bsg.upm.entity.BusinessSubSystemEntity;
import com.bsg.upm.entity.BusinessSystemEntity;
import com.bsg.upm.entity.ClusterEntity;
import com.bsg.upm.entity.DictEntity;
import com.bsg.upm.entity.HostEntity;
import com.bsg.upm.entity.MonitorEventEntity;
import com.bsg.upm.entity.ServEntity;
import com.bsg.upm.entity.SiteEntity;
import com.bsg.upm.entity.SystemConfigEntity;
import com.bsg.upm.exception.APIException;
import com.bsg.upm.http.RespJson;
import com.bsg.upm.http.RespJsonFactory;
import com.bsg.upm.util.UDPMessage;

@Service
public class MonitorAlarmService extends BaseService {

	public static final String SWITCH_ON = "on";
	public static final String SWITCH_OFF = "off";

	@Resource
	private DictDao dictDao;

	@Resource
	MonitorEventDao monitorEventDao;
	@Resource
	SystemConfigDao systemConfigDao;

	public RespJson getSwitch() throws APIException {
		try {
			sendHandleTask();
			JSONObject obj = new JSONObject();

			String valueStr = dictTypeCache.getTextFromCache(DictTypeConstants.MONITOR_ALARM,
					DictConstants.MONITOR_ALARM_SWITCH_CODE);
			obj.put("value", valueStr);

			return RespJsonFactory.buildOK(obj);

		} catch (Exception e) {
			logger.error("获取告警开关异常", e);
			throw new APIException("获取告警开关异常:" + e.getMessage());
		}

	}

	public RespJson updateSwitch(String value) throws APIException {
		try {

			DictEntity dict = dictDao.getByDictTypeCodeAndDictCode(DictTypeConstants.MONITOR_ALARM,
					DictConstants.MONITOR_ALARM_SWITCH_CODE);

			dict.setName(value);
			dictTypeCache.updateDict(dict);

			return RespJsonFactory.buildOK();

		} catch (Exception e) {
			logger.error("更新告警开关异常", e);
			throw new APIException("更新告警开关异常:" + e.getMessage());
		}

	}

	public void sendHandleTask() {
		try {

			String valueStr = dictTypeCache.getTextFromCache(DictTypeConstants.MONITOR_ALARM,
					DictConstants.MONITOR_ALARM_SWITCH_CODE);
			if (valueStr.equals(SWITCH_OFF)) {
				return;
			}
			
			SystemConfigEntity configEntity = systemConfigDao.getSysConfig();
			if (configEntity == null) {
				logger.error("get fail :the remote alert system config ip:prot form tb_sys_config");
				return;
			}

			List<MonitorEventEntity> eventEntities = monitorEventDao.listAlarmWithNoSend();
			if (eventEntities == null) {
				return;
			}


			String UDP_IP = configEntity.getAlertUdpIp();
			String UDP_PORT = configEntity.getAlertUdpPort();

			List<ClusterEntity> clusters = clusterDao.listWithoutAssociation();
			List<ServEntity> servs = servDao.listWithoutAssociation();
			List<HostEntity> hosts = hostDao.listWithoutAssociation();
			List<BusinessSystemEntity> businessSystemEntities = businessSystemDao.listWithoutAssociation();
			List<BusinessSubSystemEntity> businessSubSystemEntities = businessSubSystemDao.listWithoutAssociation();
			List<AreaEntity> areas = areaDao.listWithoutAssociation();
			List<SiteEntity> sites = siteDao.listWithoutAssociation();
			
			int sendFailCount = 0;
			for (MonitorEventEntity eventEntity : eventEntities) {

				UDPMessage message = new UDPMessage();

				message.setTimestamp(Long.toString(eventEntity.getCreateTimestamp().getTime()));
				message.setEventType("O");
				message.setEventST("O");
				message.setEventID(eventEntity.getId());
				message.setObjID(eventEntity.getObj());
				message.setEventCode(eventEntity.getId());

				String level = eventEntity.getLevel();
				if (level.equals(MonitorCommonMap.EVENT_LEVEL_CRITICAL)) {
					message.setSeverity("F");
				} else if (level.equals(MonitorCommonMap.EVENT_LEVEL_WARNING)) {
					message.setSeverity("W");
				} else if (level.equals(MonitorCommonMap.EVENT_LEVEL_NORMAL)) {
					message.setSeverity("D");
				} else if (level.equals(MonitorCommonMap.EVENT_LEVEL_INFO)) {
					message.setSeverity("I");
				}

				String clusterName = null;
				String hostName = null;
				String hostIp = null;				
				String systemName = null;
				String subSystemName = null;
				String servName = null;
				String areaName = null;

				boolean servFind = false;
				if (servs != null && eventEntity.getServId() != null) {
					for (ServEntity serv : servs) {
						if (serv.getId().equals(eventEntity.getServId())) {
							servName = serv.getServName();
							servFind = true;
							break;
						}
					}
				}

				if (!servFind && !eventEntity.getObjType().equals(MonitorCommonMap.HOST_TYPE)) {
					logger.warn(" sendHandleTask:eventEntityid " +eventEntity.getId()+ ":dont find serve");
					eventEntity.setSend(true);
					updateToDB(eventEntity);
					continue;
				}
				
				boolean hostFind = false;				
				if (hosts != null) {
					for (HostEntity host : hosts) {
						if (host.getRelateId() == null) {
							continue;
						}											
						if (host.getRelateId().equals(eventEntity.getHostRelateId())) {
							hostName = host.getName();
							hostIp = host.getSshIp();
							hostFind=true;
							break;
						}
					}
				}
				
				if (!hostFind && eventEntity.getObjType().equals(MonitorCommonMap.HOST_TYPE)) {
					logger.warn(" sendHandleTask:eventEntityid " +eventEntity.getId()+ ":dont find host");
					eventEntity.setSend(true);
					updateToDB(eventEntity);
					continue;
				}

				if (clusters != null) {
					for (ClusterEntity cluster : clusters) {
						if (cluster.getId().equals(eventEntity.getClusterId())) {
							clusterName = cluster.getName();
							break;
						}
					}
				}

				if (areas != null) {
					for (AreaEntity area : areas) {
						if (area.getId().equals(eventEntity.getAreaId())) {
							areaName = area.getName();
							break;
						}
					}
				}
				
				String SiteName = "null";
				if (sites != null) {
					for (SiteEntity site : sites) {
						if (site.getId().equals(eventEntity.getSiteId())) {
							SiteName = site.getName();
							break;
						}
					}
				}
				
				if (businessSystemEntities != null && eventEntity.getSystemId() != null) {
					for (BusinessSystemEntity businessSystem : businessSystemEntities) {
						if (businessSystem.getId().equals(eventEntity.getSystemId())) {
							systemName = businessSystem.getName();
							break;
						}
					}
				}

				if (businessSubSystemEntities != null && eventEntity.getSubSystemId() != null) {
					for (BusinessSubSystemEntity businessSubSystem : businessSubSystemEntities) {
						if (businessSubSystem.getId().equals(eventEntity.getSubSystemId())) {
							subSystemName = businessSubSystem.getName();
							break;
						}
					}
				}



				message.setSystem(clusterName + ":" + hostName + ":" + hostIp);
				message.setItem(eventEntity.getMetric() + ":" + eventEntity.getLevel());

				message.setLocationID(SiteName);

				message.setComponent(eventEntity.getOwner() + ":" + eventEntity.getObj());
				String msg = "";

				if (eventEntity.getObjType().equals(MonitorCommonMap.HOST_TYPE)) {
					msg = "[DBAAS]" + SiteName + areaName + clusterName + hostName + hostIp + eventEntity.getMetric()
							+ eventEntity.getValue();
				} else {
					msg = "[DBAAS]" + SiteName + areaName + systemName + subSystemName + servName + "鏁版嵁搴�"
							+ eventEntity.getMetric() + eventEntity.getValue();
				}

				message.setMsg(msg);
				message.setMsgAddn("");
				message.setResv("");

				if (sendUDP(message, UDP_IP, Integer.parseInt(UDP_PORT))) {
					eventEntity.setSend(true);
					eventEntity.setSendTimestap(new Date());
					updateToDB(eventEntity);
				} else {

					sendFailCount += 1;
					if (sendFailCount >= 100) {
						logger.error("sendUDP fail to  remote alert system  for 100 times");
						break;
					}

				}
			}

		} catch (Exception e) {
			logger.error("sendHandleTask fail:", e);
		}

	}

	private Boolean updateToDB(MonitorEventEntity monitorEventEntity) {

		try {
			monitorEventDao.updateSend(monitorEventEntity);
			return true;
		} catch (Exception e) {
			logger.error("monitorEventDao.update  fail:" + e);
		}

		return false;

	}

	public RespJson getShowAlarm(Map<String, Object> paramMap) throws APIException {
		try {
			JSONArray ret = new JSONArray();

			List<MonitorEventEntity> eventEntities = monitorEventDao.listAlarm(paramMap);
			if (eventEntities == null) {
				return RespJsonFactory.buildOK(ret);
			}

			List<ClusterEntity> clusters = clusterDao.listWithoutAssociation();
			List<ServEntity> servs = servDao.listWithoutAssociation();
			List<HostEntity> hosts = hostDao.listWithoutAssociation();
			List<BusinessSystemEntity> businessSystemEntities = businessSystemDao.listWithoutAssociation();
			List<BusinessSubSystemEntity> businessSubSystemEntities = businessSubSystemDao.listWithoutAssociation();

			for (MonitorEventEntity eventEntity : eventEntities) {
				JSONObject object = new JSONObject();
				object.put("name", eventEntity.getMetric());
				object.put("value", eventEntity.getValue());
				object.put("level", eventEntity.getLevel());
				object.put("create_time", eventEntity.getCreateTimestamp());
				object.put("owner", eventEntity.getOwner());

				object.put("cluster_name", null);

				boolean servFind = false;
				object.put("serv_name", null);
				if (servs != null && eventEntity.getServId() != null) {
					for (ServEntity serv : servs) {
						if (serv.getId().equals(eventEntity.getServId())) {
							object.put("serv_name", serv.getServName());
							servFind=true;
							break;
						}
					}
				}
				
				if (!servFind && !eventEntity.getObjType().equals(MonitorCommonMap.HOST_TYPE)) {
					continue;
				}
				
				boolean hostFind = false;
				object.put("host_name", null);
				if (hosts != null) {
					for (HostEntity host : hosts) {
					
						if (host.getRelateId() == null) {
							continue;
						}
						
						if (host.getRelateId().equals(eventEntity.getHostRelateId())) {
							object.put("host_name", host.getName());
							hostFind=true;
							break;
						}
					}
				}
				if (!hostFind && eventEntity.getObjType().equals(MonitorCommonMap.HOST_TYPE)) {
					continue;
				}

				if (clusters != null) {
					for (ClusterEntity cluster : clusters) {
						if (cluster.getId().equals(eventEntity.getClusterId())) {
							object.put("cluster_name", cluster.getName());
							break;
						}
					}
				}

				object.put("system_name", null);
				if (businessSystemEntities != null && eventEntity.getSystemId() != null) {
					for (BusinessSystemEntity businessSystem : businessSystemEntities) {
						if (businessSystem.getId().equals(eventEntity.getSystemId())) {
							object.put("system_name", businessSystem.getName());
							break;
						}
					}
				}

				object.put("subsystem_name", null);
				if (businessSubSystemEntities != null && eventEntity.getSubSystemId() != null) {
					for (BusinessSubSystemEntity businessSubSystem : businessSubSystemEntities) {
						if (businessSubSystem.getId().equals(eventEntity.getSubSystemId())) {
							object.put("subsystem_name", businessSubSystem.getName());
							break;
						}
					}
				}



				ret.add(object);

			}

			return RespJsonFactory.buildOK(ret);

		} catch (Exception e) {
			logger.error("getShowAlarm fail:", e);
			throw new APIException("getShowAlarm fail:" + e.getMessage());
		}

	}

	// 鍙戦�乽dp鍗忚
	private Boolean sendUDP(UDPMessage message, String ip, int port) {

		try {

			int msg_len = message.getMsg().getBytes().length;
			int msgAddn_len = message.getMsgAddn().length();
			int resv_len = message.getResv().length();
			int length = 4 + 1 + 1 + 32 + 100 + 100 + 100 + 100 + 2 + 1 + 10 + 19 + 4 + msg_len + 4 + msgAddn_len + 4
					+ resv_len;
			byte[] b = new byte[length];
			for (int i = 0; i < b.length; i++) {
				b[i] = ' ';
			}
			// 鎬诲崗璁暱搴�
			int offset_lengthByte = 0;
			byte[] lengthByte = String.valueOf(length).getBytes();
			int len_lengthByte = lengthByte.length;
			if (len_lengthByte > 4) {
				len_lengthByte = 4;
			}
			System.arraycopy(lengthByte, 0, b, offset_lengthByte, len_lengthByte);

			// 浜嬩欢绫诲瀷
			int offset_eventTypeByte = 4;
			byte[] eventTypeByte = message.getEventType().getBytes();
			int len_eventTypeByte = eventTypeByte.length;
			if (len_eventTypeByte > 1) {
				len_eventTypeByte = 1;
			}
			System.arraycopy(eventTypeByte, 0, b, offset_eventTypeByte, len_eventTypeByte);

			// 浜嬩欢鐘舵��
			int offset_eventSTByte = 5;
			byte[] eventSTByte = message.getEventST().getBytes();
			int len_eventSTByte = eventSTByte.length;
			if (len_eventSTByte > 1) {
				len_eventSTByte = 1;
			}
			System.arraycopy(eventSTByte, 0, b, offset_eventSTByte, len_eventSTByte);

			// 浜嬩欢ID
			int offset_eventID = 6;
			byte[] eventIDByte = message.getEventID().getBytes();
			int len_eventIDByte = eventIDByte.length;
			if (len_eventIDByte > 32) {
				len_eventIDByte = 32;
			}
			System.arraycopy(eventIDByte, 0, b, offset_eventID, len_eventIDByte);

			// 浜嬩欢鎵�灞炵郴缁�
			int offset_system = 38;
			byte[] systemByte = message.getSystem().getBytes("GBK");
			int len_systemByte = systemByte.length;
			if (len_systemByte > 100) {
				len_systemByte = 100;
			}
			System.arraycopy(systemByte, 0, b, offset_system, len_systemByte);

			// 浜嬩欢鎵�灞炵粍浠�
			int offset_component = 138;
			byte[] componentByte = message.getComponent().getBytes("GBK");
			int len_componentByte = componentByte.length;
			if (len_componentByte > 100) {
				len_componentByte = 100;
			}
			System.arraycopy(componentByte, 0, b, offset_component, len_componentByte);

			// 浜嬩欢鎵�灞為」鐩�
			int offset_item = 238;
			byte[] itemByte = message.getItem().getBytes("GBK");
			int len_itemByte = itemByte.length;
			if (len_itemByte > 100) {
				len_itemByte = 100;
			}
			System.arraycopy(itemByte, 0, b, offset_item, len_itemByte);

			// 瀵硅薄ID
			int offset_objID = 338;
			byte[] objIDByte = message.getObjID().getBytes();
			int len_objIDByte = objIDByte.length;
			if (len_objIDByte > 100) {
				len_objIDByte = 100;
			}
			System.arraycopy(objIDByte, 0, b, offset_objID, len_objIDByte);

			// 鎵�灞炲湴鍩�
			int offset_locationID = 438;
			byte[] locationIDByte = message.getLocationID().getBytes();
			int len_locationIDByte = locationIDByte.length;
			if (len_locationIDByte > 2) {
				len_locationIDByte = 2;
			}
			System.arraycopy(locationIDByte, 0, b, offset_locationID, len_locationIDByte);

			// 浜嬩欢涓ラ噸绛夌骇
			int offset_severity = 440;
			byte[] severityByte = message.getSeverity().getBytes();
			int len_severityByte = severityByte.length;
			if (len_severityByte > 1) {
				len_severityByte = 1;
			}
			System.arraycopy(severityByte, 0, b, offset_severity, len_severityByte);

			// 浜嬩欢浠ｇ爜
			int offset_eventCode = 441;
			byte[] eventCodeByte = message.getEventCode().getBytes();
			int len_eventCodeByte = eventCodeByte.length;
			if (len_eventCodeByte > 10) {
				len_eventCodeByte = 10;
			}
			System.arraycopy(eventCodeByte, 0, b, offset_eventCode, len_eventCodeByte);

			// 浜嬩欢鍙戠敓鏃堕棿
			int offset_timestamp = 451;
			byte[] timestampByte = message.getTimestamp().getBytes();
			int len_timestampByte = timestampByte.length;
			if (len_timestampByte > 19) {
				len_timestampByte = 19;
			}
			System.arraycopy(timestampByte, 0, b, offset_timestamp, len_timestampByte);

			// 浜嬩欢鎻忚堪鍐呭闀垮害
			int offset_msgLen = 470;
			byte[] msgLenByte = String.valueOf(msg_len).getBytes();
			int len_msgLenByte = msgLenByte.length;
			if (len_msgLenByte > 4) {
				len_msgLenByte = 4;
			}
			System.arraycopy(msgLenByte, 0, b, offset_msgLen, len_msgLenByte);

			// 浜嬩欢鎻忚堪鍐呭
			int offset_msg = 474;
			byte[] msgByte = message.getMsg().getBytes("GBK");
			int len_msgByte = msgByte.length;
			if (len_msgLenByte > 4096) {
				len_msgLenByte = 4096;
			}
			System.arraycopy(msgByte, 0, b, offset_msg, len_msgByte);

			// 浜嬩欢澶囨敞鍐呭闀垮害
			int offset_msgAddnLen = 474 + msg_len;
			byte[] msgAddnLenByte = String.valueOf(msgAddn_len).getBytes();
			int len_msgAddnLenByte = msgAddnLenByte.length;
			if (len_msgLenByte > 4) {
				len_msgLenByte = 4;
			}
			System.arraycopy(msgAddnLenByte, 0, b, offset_msgAddnLen, len_msgAddnLenByte);

			// 浜嬩欢澶囨敞鍐呭
			int offset_msgAddn = 478 + msg_len;
			byte[] msgAddnByte = message.getMsgAddn().getBytes();
			int len_msgAddnByte = msgAddnByte.length;
			if (len_msgAddnByte > 1024) {
				len_msgAddnByte = 1024;
			}
			System.arraycopy(msgAddnByte, 0, b, offset_msgAddn, len_msgAddnByte);

			// 淇濈暀瀛楁闀垮害
			int offset_resvLen = 478 + msg_len + msgAddn_len;
			byte[] resvLenByte = String.valueOf(resv_len).getBytes();
			int len_resvLenByte = resvLenByte.length;
			if (len_resvLenByte > 4) {
				len_resvLenByte = 4;
			}
			System.arraycopy(resvLenByte, 0, b, offset_resvLen, len_resvLenByte);

			// 淇濈暀瀛楁
			int offset_resv = 482 + msg_len + msgAddn_len;
			byte[] resvByte = message.getResv().getBytes();
			int len_resvByte = resvByte.length;
			if (len_resvByte > 1024) {
				len_resvByte = 1024;
			}
			System.arraycopy(resvByte, 0, b, offset_resv, len_resvByte);

			DatagramSocket datagramSocket = new DatagramSocket();
			InetAddress destination = InetAddress.getByName(ip);
			DatagramPacket datagramPacket = new DatagramPacket(b, b.length, destination, port);
			datagramSocket.send(datagramPacket);

			datagramSocket.close();

			return true;
		} catch (Exception e) {
			logger.error("sendUDP fail:" + e);

		}

		return false;
	}
}
